<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  

  
  
  
  
  
  
  <title>南辞的技术博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta property="og:type" content="website">
<meta property="og:title" content="南辞的技术博客">
<meta property="og:url" content="https://yanlidoushikeke.gitee.io/myhexo/page/3/index.html">
<meta property="og:site_name" content="南辞的技术博客">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="南辞">
<meta name="twitter:card" content="summary">
  
  
    <link rel="icon" href="/tefuir/css/images/favicon.ico">
  
  
<link rel="stylesheet" href="/tefuir/css/style.css">

  

  
  <!-- baidu webmaster push -->
  <script src='//push.zhanzhang.baidu.com/push.js'></script>
<meta name="generator" content="Hexo 5.2.0"><link rel="alternate" href="/tefuir/atom.xml" title="南辞的技术博客" type="application/atom+xml">
</head>
<body class="home blog custom-background custom-font-enabled single-author">
  <div id="page" class="hfeed site">
      <header id="masthead" class="site-header" role="banner">
    <hgroup>
      <h1 class="site-title">
        <a href="/tefuir/" title="南辞的技术博客" rel="home">南辞的技术博客</a>
      </h1>
      
        <h2 class="site-description hitokoto"></h2>
        <script type="text/javascript" src="https://v1.hitokoto.cn/?encode=js"></script>
      
    </hgroup>

    <nav id="site-navigation" class="main-navigation" role="navigation">
            <button class="menu-toggle">菜单</button>
            <a class="assistive-text" href="/#content" title="跳至内容">跳至内容</a><!--TODO-->
            <div class="menu-main-container">
                <ul id="menu-main" class="nav-menu">
                
                    <li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/tefuir/">Home</a></li>
                
                    <li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/tefuir/archives">Archives</a></li>
                
                </ul>
            </div>
    </nav>
</header>

      <div id="main" class="wrapper">
        <div id="primary" class="site-content"><div id="content" role="main">
  
    <article id="post-Ant" class="post-Ant post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/03/01/Ant/">Ant</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/03/01/Ant/" data-id="cklqcenul0000tsu04ckr45gk" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <ul>
<li><h1 id="Ant-Design-of-Vue"><a href="#Ant-Design-of-Vue" class="headerlink" title="Ant Design of Vue"></a>Ant Design of Vue</h1><h3 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h3><ul>
<li>提炼自企业级中后台产品的交互语言和视觉风格。</li>
<li>开箱即用的高质量 Vue 组件。</li>
<li>共享<a target="_blank" rel="noopener" href="http://ant-design.gitee.io/docs/spec/introduce-cn">Ant Design of React</a>设计工具体系。</li>
</ul>
<h3 id="支持环境"><a href="#支持环境" class="headerlink" title="支持环境"></a>支持环境</h3><ul>
<li><p>现代浏览器和 IE9 及以上（需要 <a target="_blank" rel="noopener" href="https://www.antdv.com/docs/vue/getting-started-cn/#%E5%85%BC%E5%AE%B9%E6%80%A7">polyfills</a>）。</p>
</li>
<li><p>支持服务端渲染。</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://electronjs.org/">Electron</a></p>
<h4 id="版本"><a href="#版本" class="headerlink" title="版本"></a>版本</h4><ul>
<li>稳定版：<a target="_blank" rel="noopener" href="https://www.npmjs.org/package/ant-design-vue"><img src="https://img.shields.io/npm/v/ant-design-vue.svg?style=flat-square" alt="npm package"></a></li>
</ul>
</li>
</ul>
<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><h3 id="使用-npm-或-yarn-安装"><a href="#使用-npm-或-yarn-安装" class="headerlink" title="使用 npm 或 yarn 安装"></a>使用 npm 或 yarn 安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ npm install ant-design-vue --save</span><br><span class="line">$ yarn add ant-design-vue</span><br></pre></td></tr></table></figure>

<h3 id="浏览器引入"><a href="#浏览器引入" class="headerlink" title="浏览器引入"></a>浏览器引入</h3><p><code>ant-design-vue/dist</code> </p>
<h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">import Vue from &#39;vue&#39;;</span><br><span class="line">import &#123; DatePicker &#125; from &#39;ant-design-vue&#39;;</span><br><span class="line">Vue.use(DatePicker);</span><br></pre></td></tr></table></figure>

<p>引入样式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import &#39;ant-design-vue&#x2F;dist&#x2F;antd.css&#39;; </span><br></pre></td></tr></table></figure>

<h3 id="按需加载"><a href="#按需加载" class="headerlink" title="按需加载"></a>按需加载</h3><p>下面两种方式都可以只加载用到的组件。</p>
<ul>
<li><p>使用 <a target="_blank" rel="noopener" href="https://github.com/ant-design/babel-plugin-import">babel-plugin-import</a>（推荐）。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; .babelrc or babel-loader option</span><br><span class="line">&#123;</span><br><span class="line">  &quot;plugins&quot;: [</span><br><span class="line">    [&quot;import&quot;, &#123; &quot;libraryName&quot;: &quot;ant-design-vue&quot;, &quot;libraryDirectory&quot;: &quot;es&quot;, &quot;style&quot;: &quot;css&quot; &#125;] &#x2F;&#x2F; &#96;style: true&#96; 会加载 less 文件</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>注意：webpack 1 无需设置 <code>libraryDirectory</code>。</p>
</blockquote>
<p>然后只需从 ant-design-vue 引入模块即可，无需单独引入样式。等同于下面手动引入的方式。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; babel-plugin-import 会帮助你加载 JS 和 CSS</span><br><span class="line">import &#123; DatePicker &#125; from &#39;ant-design-vue&#39;;</span><br></pre></td></tr></table></figure>
</li>
<li><p>手动引入</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">import DatePicker from &#39;ant-design-vue&#x2F;lib&#x2F;date-picker&#39;; &#x2F;&#x2F; 加载 JS</span><br><span class="line">import &#39;ant-design-vue&#x2F;lib&#x2F;date-picker&#x2F;style&#x2F;css&#39;; &#x2F;&#x2F; 加载 CSS</span><br><span class="line">&#x2F;&#x2F; import &#39;ant-design-vue&#x2F;lib&#x2F;date-picker&#x2F;style&#39;;         &#x2F;&#x2F; 加载 LESS</span><br></pre></td></tr></table></figure>

</li>
</ul>
</li>
</ul>
<h2 id="vue-cli引入-ant-design-vue"><a href="#vue-cli引入-ant-design-vue" class="headerlink" title="vue-cli引入 ant-design-vue"></a>vue-cli引入 ant-design-vue</h2><h5 id="1-安装脚手架工具"><a href="#1-安装脚手架工具" class="headerlink" title="1. 安装脚手架工具"></a>1. 安装脚手架工具</h5><p>​    $ npm install -g @vue/cli</p>
<p>​    #或者</p>
<p>​       $ yarn global add @vue/cli</p>
<h5 id="新建一个项目"><a href="#新建一个项目" class="headerlink" title="新建一个项目"></a>新建一个项目</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ vue create antd-demo</span><br></pre></td></tr></table></figure>

<h5 id="进入项目并启动"><a href="#进入项目并启动" class="headerlink" title="进入项目并启动"></a>进入项目并启动</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ cd antd-demo</span><br><span class="line">$ npm run serve</span><br></pre></td></tr></table></figure>

<p>此时浏览器会访问 <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080/</a> ，看到 <code>Welcome to Your Vue.js App</code> 的界面就算成功了。</p>
<h2 id="引入-antd"><a href="#引入-antd" class="headerlink" title="引入 antd"></a>引入 antd</h2><p>这是 vue-cli 生成的默认目录结构。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">├── README.md</span><br><span class="line">├── babel.config</span><br><span class="line">├── package.json</span><br><span class="line">├── public</span><br><span class="line">│   ├── favicon.ico</span><br><span class="line">│   └── index.html</span><br><span class="line">├── src</span><br><span class="line">│   ├── assets</span><br><span class="line">│   │   └── logo.png</span><br><span class="line">│   ├── components</span><br><span class="line">│   │   └── HelloWorld.vue</span><br><span class="line">│   ├── App.vue</span><br><span class="line">│   └── main.js</span><br><span class="line">└── yarn.lock</span><br></pre></td></tr></table></figure>

<p>现在从 yarn 或 npm 安装并引入 ant-design-vue。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ yarn add ant-design-vue</span><br></pre></td></tr></table></figure>

<p>修改 <code>src/main.js</code>，引入 antd 的按钮组件以及全部样式文件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">import Vue from &#39;vue&#39;;</span><br><span class="line">import Button from &#39;ant-design-vue&#x2F;lib&#x2F;button&#39;;</span><br><span class="line">import &#39;ant-design-vue&#x2F;dist&#x2F;antd.css&#39;;</span><br><span class="line">import App from &#39;.&#x2F;App&#39;;</span><br><span class="line"></span><br><span class="line">Vue.component(Button.name, Button);</span><br><span class="line"></span><br><span class="line">Vue.config.productionTip &#x3D; false;</span><br><span class="line"></span><br><span class="line">new Vue(&#123;</span><br><span class="line">  render: h &#x3D;&gt; h(App),</span><br><span class="line">&#125;).$mount(&#39;#app&#39;);</span><br></pre></td></tr></table></figure>

<p>修改 <code>src/App.vue</code>的 template 内容。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id&#x3D;&quot;app&quot;&gt;</span><br><span class="line">    &lt;img src&#x3D;&quot;.&#x2F;assets&#x2F;logo.png&quot;&gt;</span><br><span class="line">    &lt;a-button type&#x3D;&quot;primary&quot;&gt;Button&gt;&lt;&#x2F;a-button&gt;</span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>

<p>好了，现在你应该能看到页面上已经有了 antd 的蓝色按钮组件，接下来就可以继续选用其他组件开发应用了。其他开发流程你可以参考 vue-cli 的<a target="_blank" rel="noopener" href="https://github.com/vuejs/vue-cli/blob/master/README.md">官方文档</a>。</p>
<h2 id="高级配置"><a href="#高级配置" class="headerlink" title="高级配置"></a>高级配置</h2><p>我们现在已经把组件成功运行起来了，但是在实际开发过程中还有很多问题，例如上面的例子实际上加载了全部的 antd 组件的样式（对前端性能是个隐患）。</p>
<p>此时我们需要对 vue-cli 的默认配置进行自定义。</p>
<h3 id="使用-babel-plugin-import"><a href="#使用-babel-plugin-import" class="headerlink" title="使用 babel-plugin-import"></a>使用 babel-plugin-import</h3><p><a target="_blank" rel="noopener" href="https://github.com/ant-design/babel-plugin-import">babel-plugin-import</a> 是一个用于按需加载组件代码和样式的 babel 插件（<a target="_blank" rel="noopener" href="https://www.antdv.com/docs/vue/getting-started-cn/#%E6%8C%89%E9%9C%80%E5%8A%A0%E8%BD%BD">原理</a>）。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ yarn add babel-plugin-import --dev</span><br></pre></td></tr></table></figure>

<h4 id="使用-vue-cli-2-的小伙伴"><a href="#使用-vue-cli-2-的小伙伴" class="headerlink" title="使用 vue-cli 2 的小伙伴"></a>使用 vue-cli 2 的小伙伴</h4><p>修改<code>.babelrc</code>文件，配置 babel-plugin-import</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">  &#123;</span><br><span class="line">    &quot;presets&quot;: [</span><br><span class="line">      [&quot;env&quot;, &#123;</span><br><span class="line">        &quot;modules&quot;: false,</span><br><span class="line">        &quot;targets&quot;: &#123;</span><br><span class="line">          &quot;browsers&quot;: [&quot;&gt; 1%&quot;, &quot;last 2 versions&quot;, &quot;not ie &lt;&#x3D; 8&quot;]</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;],</span><br><span class="line">      &quot;stage-2&quot;</span><br><span class="line">    ],</span><br><span class="line">-   &quot;plugins&quot;: [&quot;transform-vue-jsx&quot;, &quot;transform-runtime&quot;]</span><br><span class="line">+   &quot;plugins&quot;: [</span><br><span class="line">+     &quot;transform-vue-jsx&quot;,</span><br><span class="line">+     &quot;transform-runtime&quot;,</span><br><span class="line">+     [&quot;import&quot;, &#123; &quot;libraryName&quot;: &quot;ant-design-vue&quot;, &quot;libraryDirectory&quot;: &quot;es&quot;, &quot;style&quot;: &quot;css&quot; &#125;]</span><br><span class="line">+   ]</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<h4 id="使用-vue-cli-3-的小伙伴"><a href="#使用-vue-cli-3-的小伙伴" class="headerlink" title="使用 vue-cli 3 的小伙伴"></a>使用 vue-cli 3 的小伙伴</h4><p>修改<code>babel.config.js</code>文件，配置 babel-plugin-import</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> module.exports &#x3D; &#123;</span><br><span class="line">  presets: [&quot;@vue&#x2F;app&quot;],</span><br><span class="line">+  plugins: [</span><br><span class="line">+    [</span><br><span class="line">+      &quot;import&quot;,</span><br><span class="line">+      &#123; libraryName: &quot;ant-design-vue&quot;, libraryDirectory: &quot;es&quot;, style: true &#125;</span><br><span class="line">+    ]</span><br><span class="line">+  ]</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>然后移除前面在 <code>src/main.js</code> 里全量添加的 <code>import &#39;ant-design-vue/dist/antd.css&#39;;</code> 样式代码，并且按下面的格式引入模块。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">  &#x2F;&#x2F; src&#x2F;main.js</span><br><span class="line">  import Vue from &#39;vue&#39;</span><br><span class="line">- import Button from &#39;ant-design-vue&#x2F;lib&#x2F;button&#39;;</span><br><span class="line">+ import &#123; Button &#125; from &#39;ant-design-vue&#39;;</span><br><span class="line">- import &#39;ant-design-vue&#x2F;dist&#x2F;antd.css&#39;</span><br><span class="line">  import App from &#39;.&#x2F;App&#39;</span><br><span class="line"></span><br><span class="line">  Vue.component(Button.name, Button)</span><br><span class="line"></span><br><span class="line">  Vue.config.productionTip &#x3D; false</span><br><span class="line"></span><br><span class="line">  new Vue(&#123;</span><br><span class="line">    render: h &#x3D;&gt; h(App)</span><br><span class="line">  &#125;).$mount(&quot;#app&quot;);</span><br></pre></td></tr></table></figure>

<p>最后重启 <code>npm run serve</code> 访问页面</p>
<h4 id="主题定制"><a href="#主题定制" class="headerlink" title="主题定制"></a>主题定制</h4><p><a target="_blank" rel="noopener" href="https://www.antdv.com/docs/vue/customize-theme-cn/">https://www.antdv.com/docs/vue/customize-theme-cn/</a></p>
<h1 id="国际化"><a href="#国际化" class="headerlink" title="国际化"></a>国际化</h1><p><code>ant-design-vue</code> 目前的默认文案是英文，如果需要使用其他语言，可以参考下面的方案。</p>
<h2 id="LocaleProvider"><a href="#LocaleProvider" class="headerlink" title="LocaleProvider"></a>LocaleProvider</h2><p>ant-design-vue 提供了一个 Vue 组件 <a target="_blank" rel="noopener" href="https://www.antdv.com/components/locale-provider-cn">LocaleProvider</a> 用于全局配置国际化文案。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;a-locale-provider :locale&#x3D;&quot;locale&quot;&gt;</span><br><span class="line">    &lt;App &#x2F;&gt;</span><br><span class="line">  &lt;&#x2F;a-locale-provider&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">  import zhCN from &#39;ant-design-vue&#x2F;lib&#x2F;locale-provider&#x2F;zh_CN&#39;;</span><br><span class="line">  export default &#123;</span><br><span class="line">    data() &#123;</span><br><span class="line">      return &#123;</span><br><span class="line">        locale: zhCN,</span><br><span class="line">      &#125;;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure>

<p>注意：<code>zh_CN</code> 是文件名，以下表格也遵循同样的规则。</p>
<h3 id="Button-按钮"><a href="#Button-按钮" class="headerlink" title="Button 按钮"></a>Button 按钮</h3><h5 id="何时使用"><a href="#何时使用" class="headerlink" title="何时使用"></a>何时使用</h5><p>标记了一个（或封装一组）操作命令，响应用户点击行为，触发相应的业务逻辑。</p>
<h5 id="组件注册"><a href="#组件注册" class="headerlink" title="组件注册"></a>组件注册</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">import &#123; Button &#125; from &#39;ant-design-vue&#39;;</span><br><span class="line">Vue.use(Button);</span><br></pre></td></tr></table></figure>

<h3 id="下拉菜单"><a href="#下拉菜单" class="headerlink" title="下拉菜单"></a>下拉菜单</h3><p>​   </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;a-menu slot&#x3D;&quot;overlay&quot;&gt;</span><br><span class="line"></span><br><span class="line">     &lt;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">       1st menu item</span><br><span class="line"></span><br><span class="line">     &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">     &lt;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">       2nd menu item</span><br><span class="line"></span><br><span class="line">     &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">     &lt;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">       3rd menu item</span><br><span class="line"></span><br><span class="line">     &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">   &lt;&#x2F;a-menu&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h3 id="Menu-导航菜单"><a href="#Menu-导航菜单" class="headerlink" title="Menu 导航菜单"></a>Menu 导航菜单</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line"></span><br><span class="line">  &lt;div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;a-menu v-model&#x3D;&quot;current&quot; mode&#x3D;&quot;horizontal&quot;&gt;</span><br><span class="line"></span><br><span class="line">      &lt;a-menu-item key&#x3D;&quot;mail&quot;&gt; &lt;a-icon type&#x3D;&quot;mail&quot; &#x2F;&gt;Navigation One &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">      &lt;a-menu-item key&#x3D;&quot;app&quot; disabled&gt; &lt;a-icon type&#x3D;&quot;appstore&quot; &#x2F;&gt;Navigation Two &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">      &lt;a-sub-menu&gt;</span><br><span class="line"></span><br><span class="line">        &lt;span slot&#x3D;&quot;title&quot; class&#x3D;&quot;submenu-title-wrapper&quot;</span><br><span class="line"></span><br><span class="line">          &gt;&lt;a-icon type&#x3D;&quot;setting&quot; &#x2F;&gt;Navigation Three - Submenu&lt;&#x2F;span</span><br><span class="line"></span><br><span class="line">        &gt;</span><br><span class="line"></span><br><span class="line">        &lt;a-menu-item-group title&#x3D;&quot;Item 1&quot;&gt;</span><br><span class="line"></span><br><span class="line">          &lt;a-menu-item key&#x3D;&quot;setting:1&quot;&gt;</span><br><span class="line"></span><br><span class="line">            Option 1</span><br><span class="line"></span><br><span class="line">          &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">          &lt;a-menu-item key&#x3D;&quot;setting:2&quot;&gt;</span><br><span class="line"></span><br><span class="line">            Option 2</span><br><span class="line"></span><br><span class="line">          &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">        &lt;&#x2F;a-menu-item-group&gt;</span><br><span class="line"></span><br><span class="line">        &lt;a-menu-item-group title&#x3D;&quot;Item 2&quot;&gt;</span><br><span class="line"></span><br><span class="line">          &lt;a-menu-item key&#x3D;&quot;setting:3&quot;&gt;</span><br><span class="line"></span><br><span class="line">            Option 3</span><br><span class="line"></span><br><span class="line">          &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">          &lt;a-menu-item key&#x3D;&quot;setting:4&quot;&gt;</span><br><span class="line"></span><br><span class="line">            Option 4</span><br><span class="line"></span><br><span class="line">          &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">        &lt;&#x2F;a-menu-item-group&gt;</span><br><span class="line"></span><br><span class="line">      &lt;&#x2F;a-sub-menu&gt;</span><br><span class="line"></span><br><span class="line">      &lt;a-menu-item key&#x3D;&quot;alipay&quot;&gt;</span><br><span class="line"></span><br><span class="line">        &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;antdv.com&quot; target&#x3D;&quot;_blank&quot; rel&#x3D;&quot;noopener noreferrer&quot;</span><br><span class="line"></span><br><span class="line">          &gt;Navigation Four - Link&lt;&#x2F;a</span><br><span class="line"></span><br><span class="line">        &gt;</span><br><span class="line"></span><br><span class="line">      &lt;&#x2F;a-menu-item&gt;</span><br><span class="line"></span><br><span class="line">    &lt;&#x2F;a-menu&gt;</span><br><span class="line"></span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line"></span><br><span class="line">  data() &#123;</span><br><span class="line"></span><br><span class="line">    return &#123;</span><br><span class="line"></span><br><span class="line">      current: [&#39;mail&#39;],</span><br><span class="line"></span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h3 id="Pagination-分页"><a href="#Pagination-分页" class="headerlink" title="Pagination 分页"></a>Pagination 分页</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line"></span><br><span class="line">  &lt;a-pagination v-model&#x3D;&quot;current&quot; :total&#x3D;&quot;50&quot; show-less-items &#x2F;&gt;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line"></span><br><span class="line">  data() &#123;</span><br><span class="line"></span><br><span class="line">    return &#123;</span><br><span class="line"></span><br><span class="line">      current: 2,</span><br><span class="line"></span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="多选框"><a href="#多选框" class="headerlink" title="多选框"></a>多选框</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;a-checkbox @change&#x3D;&quot;onChange&quot;&gt;</span><br><span class="line">    Checkbox</span><br><span class="line">  &lt;&#x2F;a-checkbox&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">  methods: &#123;</span><br><span class="line">    onChange(e) &#123;</span><br><span class="line">      console.log(&#96;checked &#x3D; $&#123;e.target.checked&#125;&#96;);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>更多详细内容网址如下</p>
<p><a target="_blank" rel="noopener" href="https://www.antdv.com/components/pagination-cn/">https://www.antdv.com/components/pagination-cn/</a></p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/03/01/Ant/">
    <time datetime="2021-03-01T06:42:33.000Z" class="entry-date">
        2021-03-01
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-Dockor的基本使用" class="post-Dockor的基本使用 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/02/19/Dockor%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8/">Dockor的基本使用</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/02/19/Dockor%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8/" data-id="cklcb102u0000ocu0ep8v0jej" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <h1 id="Docker基本操作"><a href="#Docker基本操作" class="headerlink" title="Docker基本操作"></a>Docker基本操作</h1><h2 id="1-关于对镜像和容器的理解"><a href="#1-关于对镜像和容器的理解" class="headerlink" title="1.关于对镜像和容器的理解"></a>1.关于对镜像和容器的理解</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Docker镜像好比操作系统的镜像（iso）</span><br><span class="line">Docker容器好比安装完成的操作系统</span><br><span class="line"># docker镜像文件运行起来之后就是我们所说的docker容器</span><br><span class="line">123</span><br></pre></td></tr></table></figure>

<p><strong>那到底什么是Docker镜像呢?</strong><br>Docker 镜像是由文件系统叠加而成(是一种文件的存储形式)。最底端是一个文件引 导系统，即 bootfs，这很像典型的 Linux/Unix 的引导文件系统。Docker 用户几乎永远不会和 引导系统有什么交互。实际上，当一个容器启动后，它将会被移动到内存中，而引导文件系 统则会被卸载，以留出更多的内存供磁盘镜像使用。Docker 容器启动是需要一些文件的， 而这些文件就可以称为 Docker 镜像。</p>
<p>Docker 把应用程序及其依赖，打包在 image 文件里面。只有通过这个文件，才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件，可以生成多个同时运行的容器实例。</p>
<p>image 是二进制文件。实际开发中，一个 image 文件往往通过继承另一个 image 文件，加上一些个性化设置而生成。举例来说，你可以在 Ubuntu 的 image 基础上，往里面加入 Apache 服务器，形成你的 image。</p>
<p>image 文件是通用的，一台机器的 image 文件拷贝到另一台机器，照样可以使用。一般来说，为了节省时间，我们应该尽量使用别人制作好的 image 文件，而不是自己制作。即使要定制，也应该基于别人的 image 文件进行加工，而不是从零开始制作。</p>
<p>为了方便共享，image 文件制作完成后，可以上传到网上的仓库。Docker 的官方仓库 Docker Hub 是最重要、最常用的 image 仓库。此外，出售自己制作的 image 文件也是可以的。</p>
<h2 id="2-Docker镜像操作"><a href="#2-Docker镜像操作" class="headerlink" title="2.Docker镜像操作"></a>2.Docker镜像操作</h2><p><strong>列出镜像</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker image ls -a1</span><br></pre></td></tr></table></figure>

<p><img src="https://img-blog.csdn.net/20180825190236927?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzE0MjQ1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="docker列出镜像"></p>
<ul>
<li>REPOSITORY：镜像所在的仓库名称</li>
<li>TAG：镜像标签</li>
<li>IMAGEID：镜像ID</li>
<li>CREATED：镜像的创建日期(不是获取该镜像的日期)</li>
<li>SIZE：镜像大小</li>
</ul>
<p>为了区分同一个仓库下的不同镜像，Docker 提供了一种称为标签(Tag)的功能。每个 镜像在列出来时都带有一个标签，例如latest、 12.10、12.04 等等。每个标签对组成特定镜像的一 些镜像层进行标记(比如，标签 12.04 就是对所有 Ubuntu12.04 镜像层的标记)。这种机制 使得同一个仓库中可以存储多个镜像。— 版本号</p>
<p>在运行同一个仓库中的不同镜像时，可以通过在仓库名后面加上一个冒号和标签名 来指定该仓库中的某一具体的镜像，例如 docker run –name custom_container_name –i –t docker.io/ubunto:12.04 /bin/bash，表明从镜像 Ubuntu:12.04 启动一个容器，而这个镜像的操 作系统就是 Ubuntu:12.04。在构建容器时指定仓库的标签也是一个好习惯。</p>
<p><strong>拉取镜像</strong><br>Docker维护了镜像仓库，分为共有和私有两种，共有的官方仓库Docker Hub(<a target="_blank" rel="noopener" href="https://hub.docker.com/">https://hub.docker.com/</a>)是最重要最常用的镜像仓库。私有仓库（Private Registry）是开发者或者企业自建的镜像存储库，通常用来保存企业 内部的 Docker 镜像，用于内部开发流程和产品的发布、版本控制。</p>
<ul>
<li>要想获取某个镜像，我们可以使用pull命令，从仓库中拉取镜像到本地，如</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker image pull library&#x2F;hello-world1</span><br></pre></td></tr></table></figure>

<p>上面代码中，docker image pull是抓取 image 文件的命令。library/hello-world是 image 文件在仓库里面的位置，其中library是 image 文件所在的组，hello-world是 image 文件的名字。</p>
<p>由于 Docker 官方提供的 image 文件，都放在library组里面，所以它的是默认组，可以省略。因此，上面的命令可以写成下面这样。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker image pull hello-world1</span><br></pre></td></tr></table></figure>

<p><strong>删除镜像</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker image rm 镜像名或镜像id</span><br><span class="line">如：</span><br><span class="line">docker image rm hello-world123</span><br></pre></td></tr></table></figure>

<p><strong>正在运行容器的镜像是无法删除的</strong><br><img src="https://img-blog.csdn.net/20180817183429836?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzE0MjQ1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="这里写图片描述"></p>
<h2 id="3-Docker容器操作"><a href="#3-Docker容器操作" class="headerlink" title="3.Docker容器操作"></a>3.Docker容器操作</h2><p><strong>创建容器</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run [option] 镜像名 [向启动容器中传入的命令]1</span><br></pre></td></tr></table></figure>

<p>常用可选参数说明：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">-i 表示以“交互模式”运行容器</span><br><span class="line">-t 表示容器启动后会进入其命令行。加入这两个参数后，容器创建就能登录进去。即 分配一个伪终端。</span><br><span class="line">--name 为创建的容器命名</span><br><span class="line">-v 表示目录映射关系(前者是宿主机目录，后者是映射到宿主机上的目录，即 宿主机目录:容器中目录)，可以使 用多个-v 做多个目录或文件映射。注意:最好做目录映射，在宿主机上做修改，然后 共享到容器上。</span><br><span class="line">-d 在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不 会自动登录容器，如果只加-i -t 两个参数，创建后就会自动进去容器)。</span><br><span class="line">-p 表示端口映射，前者是宿主机端口，后者是容器内的映射端口。可以使用多个-p 做多个端口映射</span><br><span class="line">-e 为容器设置环境变量</span><br><span class="line">--network&#x3D;host 表示将主机的网络环境映射到容器中，容器的网络与主机相同12345678</span><br></pre></td></tr></table></figure>

<p><strong>交互式容器</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">例如，创建一个交互式容器，并命名为mycentos</span><br><span class="line">docker run -it --name&#x3D;mycentos centos &#x2F;bin&#x2F;bash</span><br><span class="line">在容器中可以随意执行linux命令，就是一个ubuntu的环境，当执行exit命令退出时，该容器也随之停止。123</span><br></pre></td></tr></table></figure>

<p><strong>守护式容器</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">例如，创建一个守护式容器，并命名为mycentos2</span><br><span class="line">docker run -dit --name&#x3D;mycentos2 centos</span><br><span class="line">创建一个守护式容器:如果对于一个需要长期运行的容器来说，我们可以创建一个守护式容器。在容器内部exit退出时，容器也不会停止。123</span><br></pre></td></tr></table></figure>

<p><strong>进入已运行的容器</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker exec -it 容器名或容器id 进入后执行的第一个命令</span><br><span class="line">例如：docker exec -it mycentos2 &#x2F;bin&#x2F;bash12</span><br></pre></td></tr></table></figure>

<p><strong>查看容器</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">列出本机正在运行的容器</span><br><span class="line">docker container ls</span><br><span class="line">列出本机所有容器，包括已经终止运行的</span><br><span class="line">docker container ls --all1234</span><br></pre></td></tr></table></figure>

<p><strong>停止与启动容器</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">停止一个已经在运行的容器</span><br><span class="line">docker container stop 容器名或容器id</span><br><span class="line"></span><br><span class="line">启动一个已经停止的容器</span><br><span class="line">docker container start 容器名或容器id</span><br><span class="line"></span><br><span class="line">kill掉一个已经在运行的容器</span><br><span class="line">docker container kill 容器名或容器id12345678</span><br></pre></td></tr></table></figure>

<p><strong>删除容器</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker container rm 容器名或容器id1</span><br></pre></td></tr></table></figure>

<h2 id="4-将容器保存为镜像"><a href="#4-将容器保存为镜像" class="headerlink" title="4.将容器保存为镜像"></a>4.将容器保存为镜像</h2><p>通过如下命令将容器保存为镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker commit 容器名 镜像名1</span><br></pre></td></tr></table></figure>

<h2 id="5-镜像备份与迁移"><a href="#5-镜像备份与迁移" class="headerlink" title="5.镜像备份与迁移"></a>5.镜像备份与迁移</h2><p>可以通过save命令将镜像打包成文件，拷贝给别人使用</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker save -o 保存的文件名 镜像名1</span><br></pre></td></tr></table></figure>

<p>例如：<code>docker save -o ./centos.tar centos</code></p>
<p>对方在拿到镜像文件后，可以通过load方法，将镜像加载到本地</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker load -i .&#x2F;centos.tar</span><br></pre></td></tr></table></figure>
      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/02/19/Dockor%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8/">
    <time datetime="2021-02-19T13:01:42.000Z" class="entry-date">
        2021-02-19
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-高并发详解" class="post-高并发详解 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/02/06/%E9%AB%98%E5%B9%B6%E5%8F%91%E8%AF%A6%E8%A7%A3/">高并发详解</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/02/06/%E9%AB%98%E5%B9%B6%E5%8F%91%E8%AF%A6%E8%A7%A3/" data-id="ckkttwp760009csu064d86syu" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <p>一、什么是高并发</p>
<p>高并发（High Concurrency）是互联网分布式系统架构设计中必须考虑的因素之一，它通常是指，通过设计保证系统能够同时并行处理很多请求。</p>
<p>高并发相关常用的一些指标有响应时间（Response Time），吞吐量（Throughput），每秒查询率QPS（Query Per Second），并发用户数等。</p>
<p>响应时间：系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms，这个200ms就是系统的响应时间。</p>
<p>吞吐量：单位时间内处理的请求数量。</p>
<p>QPS：每秒响应请求数。在互联网领域，这个指标和吞吐量区分的没有这么明显。</p>
<p>并发用户数：同时承载正常使用系统功能的用户数量。例如一个即时通讯系统，同时在线量一定程度上代表了系统的并发用户数。</p>
<p>二、如何提升系统的并发能力</p>
<p>互联网分布式架构设计，提高系统并发能力的方式，方法论上主要有两种：垂直扩展（Scale Up）与水平扩展（Scale Out）。</p>
<p>垂直扩展：提升单机处理能力。垂直扩展的方式又有两种：</p>
<p>（1）增强单机硬件性能，例如：增加CPU核数如32核，升级更好的网卡如万兆，升级更好的硬盘如SSD，扩充硬盘容量如2T，扩充系统内存如128G；</p>
<p>（2）提升单机架构性能，例如：使用Cache来减少IO次数，使用异步来增加单服务吞吐量，使用无锁数据结构来减少响应时间；</p>
<p>在互联网业务发展非常迅猛的早期，如果预算不是问题，强烈建议使用“增强单机硬件性能”的方式提升系统并发能力，因为这个阶段，公司的战略往往是发展业务抢时间，而“增强单机硬件性能”往往是最快的方法。</p>
<p>不管是提升单机硬件性能，还是提升单机架构性能，都有一个致命的不足：单机性能总是有极限的。所以互联网分布式架构设计高并发终极解决方案还是水平扩展。</p>
<p>水平扩展：只要增加服务器数量，就能线性扩充系统性能。水平扩展对系统架构设计是有要求的，如何在架构各层进行可水平扩展的设计，以及互联网公司架构各层常见的水平扩展实践，是本文重点讨论的内容。</p>
<p>三、常见的互联网分层架构</p>
<p>常见互联网分布式架构，分为：</p>
<p>（1）客户端层：典型调用方是浏览器browser或者手机应用APP</p>
<p>（2）反向代理层：系统入口，反向代理</p>
<p>（3）站点应用层：实现核心应用逻辑，返回html或者json</p>
<p>（4）服务层：如果实现了服务化，就有这一层</p>
<p>（5）数据-缓存层：缓存加速访问存储</p>
<p>（6）数据-数据库层：数据库固化数据存储</p>
<p>整个系统各层次的水平扩展，又分别是如何实施的呢？</p>
<p>四、分层水平扩展架构实践</p>
<p>反向代理层的水平扩展 </p>
<p>反向代理层的水平扩展，是通过“DNS轮询”实现的：dns-server对于一个域名配置了多个解析ip，每次DNS解析请求来访问dns-server，会轮询返回这些ip。</p>
<p>当nginx成为瓶颈的时候，只要增加服务器数量，新增nginx服务的部署，增加一个外网ip，就能扩展反向代理层的性能，做到理论上的无限高并发。</p>
<p>站点层的水平扩展 </p>
<p>站点层的水平扩展，是通过“nginx”实现的。通过修改nginx.conf，可以设置多个web后端。</p>
<p>当web后端成为瓶颈的时候，只要增加服务器数量，新增web服务的部署，在nginx配置中配置上新的web后端，就能扩展站点层的性能，做到理论上的无限高并发。</p>
<p>服务层的水平扩展</p>
<p>服务层的水平扩展，是通过“服务连接池”实现的。</p>
<p>站点层通过RPC-client调用下游的服务层RPC-server时，RPC-client中的连接池会建立与下游服务多个连接，当服务成为瓶颈的时候，只要增加服务器数量，新增服务部署，在RPC-client处建立新的下游服务连接，就能扩展服务层性能，做到理论上的无限高并发。如果需要优雅的进行服务层自动扩容，这里可能需要配置中心里服务自动发现功能的支持。</p>
<p>数据层的水平扩展</p>
<p>在数据量很大的情况下，数据层（缓存，数据库）涉及数据的水平扩展，将原本存储在一台服务器上的数据（缓存，数据库）水平拆分到不同服务器上去，以达到扩充系统性能的目的。</p>
<p>互联网数据层常见的水平拆分方式有这么几种，以数据库为例：</p>
<p>按照范围水平拆分 </p>
<p>每一个数据服务，存储一定范围的数据，上图为例：</p>
<p>user0库，存储uid范围1-1kw</p>
<p>user1库，存储uid范围1kw-2kw</p>
<p>这个方案的好处是：</p>
<p>（1）规则简单，service只需判断一下uid范围就能路由到对应的存储服务；</p>
<p>（2）数据均衡性较好；</p>
<p>（3）比较容易扩展，可以随时加一个uid[2kw,3kw]的数据服务；</p>
<p>不足是：</p>
<p>（1）      请求的负载不一定均衡，一般来说，新注册的用户会比老用户更活跃，大range的服务请求压力会更大；</p>
<p>按照哈希水平拆分</p>
<p><img src="https://img2018.cnblogs.com/blog/1576270/201902/1576270-20190206101555016-399292825.png" alt="img"></p>
<p>每一个数据库，存储某个key值hash后的部分数据，上图为例：</p>
<p>user0库，存储偶数uid数据</p>
<p>user1库，存储奇数uid数据</p>
<p>这个方案的好处是：</p>
<p>（1）规则简单，service只需对uid进行hash能路由到对应的存储服务；</p>
<p>（2）数据均衡性较好；</p>
<p>（3）请求均匀性较好；</p>
<p>不足是：</p>
<p>（1）不容易扩展，扩展一个数据服务，hash方法改变时候，可能需要进行数据迁移；</p>
<p>这里需要注意的是，通过水平拆分来扩充系统性能，与主从同步读写分离来扩充数据库性能的方式有本质的不同。</p>
<p>通过水平拆分扩展数据库性能：</p>
<p>（1）每个服务器上存储的数据量是总量的1/n，所以单机的性能也会有提升；</p>
<p>（2）n个服务器上的数据没有交集，那个服务器上数据的并集是数据的全集；</p>
<p>（3）数据水平拆分到了n个服务器上，理论上读性能扩充了n倍，写性能也扩充了n倍（其实远不止n倍，因为单机的数据量变为了原来的1/n）；</p>
<p>通过主从同步读写分离扩展数据库性能：</p>
<p>（1）每个服务器上存储的数据量是和总量相同；</p>
<p>（2）n个服务器上的数据都一样，都是全集；</p>
<p>（3）理论上读性能扩充了n倍，写仍然是单点，写性能不变；</p>
<p>缓存层的水平拆分和数据库层的水平拆分类似，也是以范围拆分和哈希拆分的方式居多，就不再展开。</p>
<p>五、总结</p>
<p>高并发（High Concurrency）是互联网分布式系统架构设计中必须考虑的因素之一，它通常是指，通过设计保证系统能够同时并行处理很多请求。</p>
<p>提高系统并发能力的方式，方法论上主要有两种：垂直扩展（Scale Up）与水平扩展（Scale Out）。前者垂直扩展可以通过提升单机硬件性能，或者提升单机架构性能，来提高并发性，但单机性能总是有极限的，互联网分布式架构设计高并发终极解决方案还是后者：水平扩展。</p>
<p>互联网分层架构中，各层次水平扩展的实践又有所不同：</p>
<p>（1）反向代理层可以通过“DNS轮询”的方式来进行水平扩展；</p>
<p>（2）站点层可以通过nginx来进行水平扩展；</p>
<p>（3）服务层可以通过服务连接池来进行水平扩展；</p>
<p>（4）数据库可以按照数据范围，或者数据哈希的方式来进行水平扩展；</p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/02/06/%E9%AB%98%E5%B9%B6%E5%8F%91%E8%AF%A6%E8%A7%A3/">
    <time datetime="2021-02-06T14:18:14.000Z" class="entry-date">
        2021-02-06
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-简述vue和django的工作流程" class="post-简述vue和django的工作流程 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/01/21/%E7%AE%80%E8%BF%B0vue%E5%92%8Cdjango%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B/">简述vue和django的工作流程</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/01/21/%E7%AE%80%E8%BF%B0vue%E5%92%8Cdjango%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B/" data-id="ckkttwp6y0007csu08vjoeb0f" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <h4 id="简述vue和django的工作流程，django中间件的作用以及请求顺序"><a href="#简述vue和django的工作流程，django中间件的作用以及请求顺序" class="headerlink" title="简述vue和django的工作流程，django中间件的作用以及请求顺序"></a>简述vue和django的工作流程，django中间件的作用以及请求顺序</h4><ul>
<li>中间件是介于request 和 response 处理之间的一道处理过程，用于全局范围改变Django的输入和输出，简单的来说中间件是帮助我们在视图函数指向之前和执行之后都可以做一些额外的操作 </li>
<li>Django项目中默认启用了csrf保护，每次请求通过csrf中间件检查请求是否是有正确的token值；当用户发送请求时，通过自定义的认证中间件，判断用户是否已经登录，未登录就去登录 </li>
</ul>
<p>注册：</p>
<p>class Register(View):<br>    def post(self,request):<br>        phone = request.POST.GET(‘phone’)<br>        img = request.POST.GET(‘img’)<br>        nick_name = request.POST.GET(‘nick_name’)<br>        obj_list = models.User.objects.filter(nick_name = nick_name)<br>        if obj_list:<br>            return HttpResponse({‘msg’: ‘用户已存在’,’code’:200})</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">models.User.objects.create(nick_name&#x3D;nick_name,img&#x3D;img,phone&#x3D;phone)</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>获取数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">def Get(self, request):</span><br><span class="line">    user_liats &#x3D; models.User.objects.all()</span><br><span class="line">    user_liat &#x3D; []</span><br><span class="line">    for user_obj in user_liats:</span><br><span class="line">        user_liat.append(&#123;</span><br><span class="line">            &#39;phone&#39; : user_obj.phone,</span><br><span class="line">            &#39;img&#39; : user_obj.img,</span><br><span class="line">            &#39;nick_name&#39; : user_obj.nick_name,</span><br><span class="line">        &#125;)</span><br><span class="line">    return HttpResponse(user_liat)</span><br></pre></td></tr></table></figure>

<p>修改数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">def put(self, request):</span><br><span class="line">    data &#x3D; json.loads(request.body.decode())</span><br><span class="line">    phone &#x3D; data.GET(&#39;phone&#39;)</span><br><span class="line">    img &#x3D; data.GET(&#39;img&#39;)</span><br><span class="line">    nick_name &#x3D; data.GET(&#39;nick_name&#39;)</span><br><span class="line">    user_object &#x3D; models.User.objects.filter(nick_name&#x3D;nick_name,phone&#x3D;phone,img&#x3D;img).first()</span><br><span class="line">    user_object.nick_name &#x3D; nick_name</span><br><span class="line">    nick_name &#x3D; request.POST.GET(&#39;nick_name&#39;)</span><br><span class="line">    user_object.save()</span><br><span class="line">    return HttpResponse(&#123;&#39;msg&#39;: &#39;修改成功&#39;, &#39;code&#39;: 200&#125;)</span><br></pre></td></tr></table></figure>

<p>什么是RESTful？</p>
<ul>
<li>使用https来通信</li>
<li>域名（子域名方式或url方式）</li>
<li>版本（如果有版本在域名后加版本号）</li>
<li>面向资源编程（认为每个对象都是资源）</li>
<li>methods（GET POST PUT DELECT POTCH)</li>
<li>过滤，分页，排序：通过URL上传参的形式传递搜索条件</li>
<li>状态码</li>
</ul>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/01/21/%E7%AE%80%E8%BF%B0vue%E5%92%8Cdjango%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B/">
    <time datetime="2021-01-21T08:41:31.000Z" class="entry-date">
        2021-01-21
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-selenium模拟注册，登陆以及图片验证码的生成" class="post-selenium模拟注册，登陆以及图片验证码的生成 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/01/19/selenium%E6%A8%A1%E6%8B%9F%E6%B3%A8%E5%86%8C%EF%BC%8C%E7%99%BB%E9%99%86%E4%BB%A5%E5%8F%8A%E5%9B%BE%E7%89%87%E9%AA%8C%E8%AF%81%E7%A0%81%E7%9A%84%E7%94%9F%E6%88%90/" data-id="ckkttwp6v0005csu0b1z29u45" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <p>title: selenium<br>date: 2021-03-03 09:49:25<br>tags:</p>
<h1 id="selenium模拟注册，登陆以及图片验证码的生成"><a href="#selenium模拟注册，登陆以及图片验证码的生成" class="headerlink" title="selenium模拟注册，登陆以及图片验证码的生成"></a>selenium模拟注册，登陆以及图片验证码的生成</h1><p>1.模拟注册</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">#selenum 模拟注册</span><br><span class="line">from selenium import webdriver</span><br><span class="line"></span><br><span class="line">from selenium.webdriver import ActionChains</span><br><span class="line"></span><br><span class="line">#生成浏览器对象 chromedriver.exe的路径</span><br><span class="line">browser &#x3D; webdriver.Chrome(&#39;C:&#x2F;Users\逸可\AppData\Local\Google\Chrome\Application\chromedriver_win32\chromedriver.exe&#39;)</span><br><span class="line"></span><br><span class="line">#打开页面</span><br><span class="line">browser.get(&#39;http:&#x2F;&#x2F;127.0.0.1:8080&#x2F;head&#x2F;&#39;)</span><br><span class="line"></span><br><span class="line">#元素选择</span><br><span class="line">browser.find_elements_by_tag_name(&quot;input&quot;)[2].send_keys(&#39;南辞&#39;)</span><br><span class="line">browser.find_elements_by_tag_name(&quot;input&quot;)[3].send_keys(&#39;123&#39;)</span><br><span class="line">browser.find_elements_by_tag_name(&quot;input&quot;)[4].send_keys(&#39;123&#39;)</span><br><span class="line">browser.find_elements_by_tag_name(&quot;input&quot;)[5].send_keys(&#39;1234876543&#39;)</span><br><span class="line">browser.find_elements_by_tag_name(&quot;input&quot;)[6].send_keys(&#39;12345@qq.com&#39;)</span><br><span class="line"></span><br><span class="line">#点击登录</span><br><span class="line">browser.find_element_by_class_name(&#39;van-button--primary&#39;).click()</span><br></pre></td></tr></table></figure>

<p>2.模拟登陆</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">#selenum 模拟登陆</span><br><span class="line">from selenium import webdriver</span><br><span class="line"></span><br><span class="line">from selenium.webdriver import ActionChains</span><br><span class="line"></span><br><span class="line">#生成浏览器对象</span><br><span class="line">browser &#x3D; webdriver.Chrome(&#39;C:&#x2F;Users\逸可\AppData\Local\Google\Chrome\Application\chromedriver_win32\chromedriver.exe&#39;)</span><br><span class="line"></span><br><span class="line">#打开页面</span><br><span class="line">browser.get(&#39;http:&#x2F;&#x2F;127.0.0.1:8080&#x2F;denglu&#x2F;&#39;)</span><br><span class="line"></span><br><span class="line">#元素选择</span><br><span class="line">browser.find_elements_by_tag_name(&quot;input&quot;)[0].send_keys(&#39;111&#39;)</span><br><span class="line">browser.find_elements_by_tag_name(&quot;input&quot;)[1].send_keys(&#39;123&#39;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#拖拽动作</span><br><span class="line">action &#x3D; ActionChains(browser)</span><br><span class="line">#获取拖拽动作的标签</span><br><span class="line">button &#x3D; browser.find_element_by_class_name(&quot;dv_handler&quot;)</span><br><span class="line"></span><br><span class="line">#按住不松，拖动</span><br><span class="line">action.click_and_hold(button).perform()</span><br><span class="line">action.reset_actions()</span><br><span class="line">action.move_by_offset(280,0).perform()</span><br><span class="line"></span><br><span class="line">#点击登录</span><br><span class="line">browser.find_element_by_class_name(&#39;van-button--primary&#39;).click()</span><br></pre></td></tr></table></figure>

<p>3.图片验证码</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mycode</span>(<span class="params">APIView</span>):</span></span><br><span class="line">   <span class="function"><span class="keyword">def</span> <span class="title">get_random_color</span>(<span class="params">self</span>):</span></span><br><span class="line">      R = random.randrange(<span class="number">255</span>)</span><br><span class="line">      G = random.randrange(<span class="number">255</span>)</span><br><span class="line">      B = random.randrange(<span class="number">255</span>)</span><br><span class="line">      <span class="keyword">return</span> (R,G,B)</span><br><span class="line">   <span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self,request</span>):</span></span><br><span class="line">      <span class="comment">#定义画布</span></span><br><span class="line">      img_size = (<span class="number">120</span>,<span class="number">50</span>)</span><br><span class="line"></span><br><span class="line">      <span class="comment">#定义图像对象</span></span><br><span class="line">      image = Image.new(<span class="string">&#x27;RGB&#x27;</span>,img_size,<span class="string">&#x27;white&#x27;</span>)</span><br><span class="line">      <span class="comment">#定义画笔</span></span><br><span class="line">      draw = ImageDraw.Draw(image,<span class="string">&#x27;RGB&#x27;</span>)</span><br><span class="line">      <span class="comment">#定义字符串</span></span><br><span class="line">      source = <span class="string">&#x27;qwertiop234gh&#x27;</span></span><br><span class="line">      <span class="comment">#定义容器</span></span><br><span class="line">      code_str = <span class="string">&#x27;&#x27;</span></span><br><span class="line">      <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">4</span>):</span><br><span class="line">         <span class="comment">#获取字符串颜色</span></span><br><span class="line">         text_color = self.get_random_color()</span><br><span class="line">         <span class="comment">#获取随机字符</span></span><br><span class="line">         tem_num = random.randrange(<span class="built_in">len</span>(source))</span><br><span class="line">         random_str = source[tem_num]</span><br><span class="line">         code_str += random_str</span><br><span class="line">         draw.text((<span class="number">10</span>+<span class="number">30</span>*i,<span class="number">20</span>),random_str,text_color)</span><br><span class="line">      buf = io.BytesIO()</span><br><span class="line">      image.save(buf,<span class="string">&#x27;png&#x27;</span>)</span><br><span class="line">      <span class="comment">#保存验证码</span></span><br><span class="line">      request.session[<span class="string">&#x27;code&#x27;</span>] = code_str</span><br><span class="line">      <span class="keyword">return</span> HttpResponse(buf.getvalue(),<span class="string">&#x27;image/pag&#x27;</span>)</span><br></pre></td></tr></table></figure>

<p>图片验证码的前端</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">&lt;div&gt;</span><br><span class="line">    &lt;van-cell-group&gt;</span><br><span class="line"></span><br><span class="line">      &lt; img: src &#x3D; &#39;src&#39; @ click &#x3D; &quot;changecode&quot; &gt;</span><br><span class="line"></span><br><span class="line">   &lt;&#x2F;van-cell-group&gt;</span><br><span class="line"></span><br><span class="line">   &lt;van-field v-model&#x3D;&quot;code&quot; lable &#x3D; &#39;验证码&#39;placeholder &#x3D; &quot;请输入验证码&quot; class&#x3D;&quot;img&quot;&gt;</span><br><span class="line"></span><br><span class="line">   &lt;&#x2F;van-field&gt;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;div&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">methods: &#123;</span><br><span class="line">        &#x2F;&#x2F;变更验证码</span><br><span class="line">        changecode()&#123;</span><br><span class="line">                var num &#x3D; Math.ceil(Math.random()*10);</span><br><span class="line">                this.src &#x3D; this.src + &#39;?num&#39; + num;</span><br><span class="line">        &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">img&#123;</span><br><span class="line">	#鼠标无需点击就能更换验证码</span><br><span class="line">    cursor: pointer;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;style&gt;</span><br></pre></td></tr></table></figure>



<p>​      </p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/01/19/selenium%E6%A8%A1%E6%8B%9F%E6%B3%A8%E5%86%8C%EF%BC%8C%E7%99%BB%E9%99%86%E4%BB%A5%E5%8F%8A%E5%9B%BE%E7%89%87%E9%AA%8C%E8%AF%81%E7%A0%81%E7%9A%84%E7%94%9F%E6%88%90/">
    <time datetime="2021-01-19T12:22:49.270Z" class="entry-date">
        2021-01-19
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-git 上传" class="post-git 上传 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/01/19/git%20%E4%B8%8A%E4%BC%A0/" data-id="ckkttwp6d0000csu0gvhngetg" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <p> <strong>一：Git是什么？</strong></p>
<p>​       Git是目前世界上最先进的分布式版本控制系统。</p>
<p><strong>二：SVN与Git的最主要的区别？</strong></p>
<p>​      SVN是集中式版本控制系统，版本库是集中放在中央服务器的，而干活的时候，用的都是自己的电脑，所以首先要从中央服务器哪里得到最新的版本，然后干活，干完后，需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作，如果在局域网还可以，带宽够大，速度够快，如果在互联网下，如果网速慢的话，就纳闷了。</p>
<p>​      Git是分布式版本控制系统，那么它就没有中央服务器的，每个人的电脑就是一个完整的版本库，这样，工作的时候就不需要联网了，因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库，那多个人如何协作呢？比如说自己在电脑上改了文件A，其他人也在电脑上改了文件A，这时，你们两之间只需把各自的修改推送给对方，就可以互相看到对方的修改了。</p>
<p>三：理解工作区与暂存区的区别？</p>
<p>​     <strong>工作区：</strong>就是你在电脑上看到的目录，比如目录下testgit里的文件(.git隐藏目录版本库除外)。或者以后需要再新建的目录文件等等都属于工作区范畴。</p>
<p>​      <strong>版本库**</strong>(Repository)<strong>**：</strong>工作区有一个隐藏目录.git,这个不属于工作区，这是版本库。其中版本库里面存了很多东西，其中最重要的就是stage(暂存区)，还有Git为我们自动创建了第一个分支master,以及指向master的一个指针HEAD。</p>
<p>我们前面说过使用Git提交文件到版本库有两步：</p>
<p>  第一步：是使用 git add 把文件添加进去，实际上就是把文件添加到暂存区。</p>
<p>  第二步：使用git commit提交更改，实际上就是把暂存区的所有内容提交到当前分支上。</p>
<p>四.创建git本地仓库</p>
<p><strong>git init</strong></p>
<p>此时会出现提示 : inialized empty Git repository in d://com/liu/.git</p>
<p>4.查看git状态</p>
<p><strong>git status</strong></p>
<p>一般来说会显示需要提交的文件（uncommited）和未追踪的文件（untracked）</p>
<p>uncommited：已有的，刚被修改尚未提交的</p>
<p>untracked：原先没有的，新建的</p>
<p>5.添加git文件到暂存区（需要和版本库区分）</p>
<p><strong>git add <name></strong></p>
<p>6.git提交文件</p>
<p><strong>git commit -m “add a function in test.java”</strong></p>
<p>-m表示注释，为提交时的说明，必须要有！</p>
<p>7.git删除文件（夹）</p>
<p><strong>git rm test.txt</strong> //删除文件</p>
<p><strong>git rm -r filebook</strong> //删除文件夹</p>
<p>git rm和直接删除的区别在于git rm会将此文件的操作记录删除，而直接删除仅仅是删除了物理文件，没有删除和此文件相关的记录。git rm后会在版本库产生区别（有操作日志），而直接删除没有。</p>
<p>可以用下面两种操作在版本库中删除文件：</p>
<p><strong>git rm test.txt</strong> =&gt; <strong>git commit -m ‘delete a file’</strong></p>
<p><strong>rm test.txt</strong> =&gt; <strong>git commit -am ‘delete a file’</strong></p>
<p>注意：命令git rm用于删除一个文件。如果一个文件已经被提交到版本库，那么你永远不用担心误删，但是要小心，你只能恢复文件到最新版本，你会 丢失最近一次提交后你修改的内容。</p>
<p>8.git操作日志</p>
<p><strong>git log –decorate –graph –oneline –all</strong> #显示当前及之前的版本号</p>
<p><strong>git log –pretty=oneline</strong> #将版本历史显示为一行， 历史版本号全部显示</p>
<p><strong>git log –pretty=oneline –abbrev-commit</strong> #将版本历史显示为一行， 历史版本号部分显示</p>
<p><strong>git log –graph</strong> #查看分支合并图</p>
<p>9.版本回退</p>
<p>执行版本退回后，本地工作区的内容会自动和回退到的版本库版本的内容保持同步</p>
<p><strong>git reset –hard HEAD^</strong> 回退到上一个版本</p>
<p><strong>git reset –hard HEAD^^</strong> 回退到上上个版本，以此类推，一次提交即为一个版本</p>
<p><strong>git reset –hard</strong> <em>e9efa77</em> 回退到 <em>e9efa77</em> 版本</p>
<p>10.git还原操作</p>
<p>丢弃工作区的操作，但不会丢失暂存区的操作(add操作能将更改添加到暂存区)，实际上就是用版本库里的版本替换工作区的版本，无论工作区是修改还是删除，都可以“一键还原”</p>
<p><strong>git checkout – readme.txt</strong></p>
<p>11.git暂存区撤销操作</p>
<p>工作区修改了文件，而且执行了add，但还没执行commit，暂存区还是可以撤销的</p>
<p><strong>git reset HEAD readme.txt</strong></p>
<p>备注：git reset命令既可以回退版本，也可以把暂存区的修改回退到工作区。当我们用HEAD时，表示最新的版本。</p>
<p>五.与github/gitee协同使用（git代码托管服务器）</p>
<p>和GitHub相比，码云（Gitee）也提供免费的Git仓库。此外，还集成了代码质量检测、项目演示等功能。对于团队协作开发，码云还提供了项目管理、代码托管、文档管理的服务，5人以下小团队免费。</p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/01/19/git%20%E4%B8%8A%E4%BC%A0/">
    <time datetime="2021-01-19T12:22:49.268Z" class="entry-date">
        2021-01-19
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-纯静态博客系统" class="post-纯静态博客系统 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/01/19/%E7%BA%AF%E9%9D%99%E6%80%81%E5%8D%9A%E5%AE%A2%E7%B3%BB%E7%BB%9F/">纯静态博客系统</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/01/19/%E7%BA%AF%E9%9D%99%E6%80%81%E5%8D%9A%E5%AE%A2%E7%B3%BB%E7%BB%9F/" data-id="ckkttwp700008csu02s0h1dri" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <p>首先，可以去go的官网网站下载安装包  <a target="_blank" rel="noopener" href="https://golang.org/dl/">https://golang.org/dl/</a> 然后直接双击安装即可，不需要配置环境变量，因为安装过程自动配置，安装完毕后，打开命令行，输入</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">go version</span><br></pre></td></tr></table></figure>

<p>显示主版本号即表示安装成功</p>
<p>然后，可以进行hugo的在线源码编译安装，打开命令行，输入下面的命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">go get -u -v github.com&#x2F;spf13&#x2F;hugo</span><br><span class="line">go build -o hugo main.go</span><br><span class="line">mv hugo $GOPATH&#x2F;bin</span><br></pre></td></tr></table></figure>

<p>如果你不想在线编译安装，也可以去hugo的官网 <a target="_blank" rel="noopener" href="https://github.com/gohugoio/hugo/releases">https://github.com/gohugoio/hugo/releases</a> 下载稳定版的压缩包，解压之后配置一下环境变量也可以</p>
<p>装完以后，在命令行内输入</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hugo version</span><br></pre></td></tr></table></figure>

<p>打印出版本号即表示hugo安装成功</p>
<p>在命令行中输入命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hugo new site hugo_blog</span><br></pre></td></tr></table></figure>

<p>就生成了一个名字为hugo_blog的新站点，可以感受到速度非常快，和vue.js创建新站点的速度比起来简直天差地别</p>
<p>打开配置文件config.toml，这是hugo的站点的相关配置，可以进行一些个性化的定制，改为下面这样：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">baseURL &#x3D; &quot;&#x2F;&quot;</span><br><span class="line">languageCode &#x3D; &quot;en-us&quot;</span><br><span class="line">title &#x3D; &quot;我的博客&quot;</span><br><span class="line">#指定主题</span><br><span class="line">theme &#x3D; &quot;hyde&quot;</span><br><span class="line"></span><br><span class="line">[params]</span><br><span class="line">#博客简介</span><br><span class="line">description &#x3D; &quot;这里是XX的个人博客&quot;</span><br><span class="line">#博客主题颜色</span><br><span class="line">themeColor &#x3D; &quot;theme-base-08&quot;</span><br></pre></td></tr></table></figure>

<p>可以看到我们制定了一个主题hyde，添加了Theme后的站点才有血有肉，丰富多彩。</p>
<p>更多的主题可以在这个上面下载，都是免费而开源的：<a target="_blank" rel="noopener" href="https://themes.gohugo.io/">https://themes.gohugo.io/</a></p>
<p>进入到站点内的themes目录，输入命令下载hyde主题，hugo有很多漂亮的主题可以选择</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https:&#x2F;&#x2F;github.com&#x2F;spf13&#x2F;hyde.git</span><br></pre></td></tr></table></figure>

<p>结构和样式有了，我们还没有内容。我们来创建站点的第一篇文章</p>
<p>输入命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hugo new one.md</span><br></pre></td></tr></table></figure>

<p>hugo在content下创建one.md文件，我们编写一些文件内容：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">date: &quot;2021-01-11&quot;</span><br><span class="line">title: &quot;第一篇文章&quot;</span><br><span class="line">---</span><br><span class="line"></span><br><span class="line">### hello word</span><br><span class="line"></span><br><span class="line">123123123</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">​&#96;&#96;&#96;</span><br><span class="line">print(&#39;hello world&#39;)</span><br><span class="line">​&#96;&#96;&#96;</span><br></pre></td></tr></table></figure>

<p>然后在命令行中输入</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hugo server</span><br></pre></td></tr></table></figure>

<p>来热启动项目</p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/01/19/%E7%BA%AF%E9%9D%99%E6%80%81%E5%8D%9A%E5%AE%A2%E7%B3%BB%E7%BB%9F/">
    <time datetime="2021-01-19T12:03:44.000Z" class="entry-date">
        2021-01-19
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-hexo搭建个人网站" class="post-hexo搭建个人网站 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/01/19/hexo%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/">hexo搭建个人网站</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/01/19/hexo%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/" data-id="ckkttwp6p0002csu04fy418ou" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <h3 id="使用Hexo建立博客"><a href="#使用Hexo建立博客" class="headerlink" title="使用Hexo建立博客"></a>使用Hexo建立博客</h3><p>​    在之前的一篇文章中，介绍了如何使用Hugo在<a target="_blank" rel="noopener" href="https://v3u.cn/a_id_81">三分钟之内建立一个简单的个人博客系统</a>，它是基于go lang的，其实，市面上还有一款类似的静态页生成器，就是Hexo 读音/hækso/ ，它是基于node.js的，和Hugo一样，Hexo 正常来说，不需要部署到我们的服务器上，我们的服务器上保存的，其实是基于在hexo通过markdown编写的文章，然后hexo帮我们生成静态的html页面，然后，将生成的html上传到我们的服务器。简而言之：hexo是个静态页面生成、上传的工具。</p>
<p>​    首先安装Hexo，在此之前，请确保电脑里已经安装好新版的node.js</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g hexo-cli</span><br></pre></td></tr></table></figure>

<p>​    如果感觉安装速度比较慢，可以为npm指定国内的源</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config set registry https:&#x2F;&#x2F;registry.npm.taobao.org</span><br></pre></td></tr></table></figure>

<p>​    安装完成后，创建博客项目</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo init blog</span><br></pre></td></tr></table></figure>

<p>​    这样，就建立起了一个blog文件夹，进入到blog目录下 cd blog，建立第一篇文章</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new myfirst</span><br></pre></td></tr></table></figure>

<p>​    然后运行hexo服务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo server</span><br></pre></td></tr></table></figure>

<p>​    就可以在本地访问你的博客网站了，默认端口号是4000</p>
<p>​    那么如何将博客网站打包呢？直接运行打包命令，这样就能使用 Hexo 引擎将 Markdown 格式的文件解析成可以使用浏览器查看的 HTML 文件，HTML 文件存储在 blog/public 目录下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo generate</span><br></pre></td></tr></table></figure>

<p>​    下面我们可以配置一下hexo主题，Hexo 提供了默认主题 landscape，主题的位置在 blog -&gt;themes 文件夹下。主题根据自己喜好可以在网上找到:<a target="_blank" rel="noopener" href="https://hexo.io/themes/">https://hexo.io/themes/</a></p>
<p>​    主题都放在blog/themes文件夹下面，这我们下载一个新的主题</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir themes&#x2F;next</span><br><span class="line">git clone --branch v5.1.2 https:&#x2F;&#x2F;github.com&#x2F;iissnan&#x2F;hexo-theme-next themes&#x2F;next</span><br></pre></td></tr></table></figure>

<p>​    然后在修改 /blog/config.yml 文件，将其中的 theme 改成 next</p>
<p>​    最后，将打包好的public目录上传到服务器，使用nginx代理访问就可以了</p>
<p>​    如果没有自己的域名和服务器怎么办？没关系，可以申请 Github 免费静态内容空间，在github.com注册一个账号，然后创建一个新的仓库</p>
<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190625/20190625080452_43440.png" alt="img"></p>
<p>​    仓库名称一定要定义成 账号名.github.io，这种形式，注意账号名一定要和你的github当前登录的账号吻合</p>
<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190625/20190625080756_40947.png" alt="img">  </p>
<p>​    这样你的静态内容空间就已经创建好了，在浏览器输入你的 <a target="_blank" rel="noopener" href="https://zcxey2911.github.io/">https://你的账号.github.io/</a> 就可以访问了。</p>
<p>​    将之前打包好的public中的文件push到刚刚创建好的github仓库中去</p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/01/19/hexo%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/">
    <time datetime="2021-01-19T11:56:03.000Z" class="entry-date">
        2021-01-19
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-jwt的使用" class="post-jwt的使用 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/01/19/jwt%E7%9A%84%E4%BD%BF%E7%94%A8/">jwt的使用</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/01/19/jwt%E7%9A%84%E4%BD%BF%E7%94%A8/" data-id="ckkttwp6r0003csu0eku5f1wh" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <h2 id="1、在INSTALLED-APPS中加入’rest-framework-authtoken’"><a href="#1、在INSTALLED-APPS中加入’rest-framework-authtoken’" class="headerlink" title="1、在INSTALLED_APPS中加入’rest_framework.authtoken’,"></a>1、在INSTALLED_APPS中加入’rest_framework.authtoken’,</h2><p>INSTALLED_APPS = [<br>    ‘’’<br>    ‘rest_framework.authtoken’,  #<br>    ‘’’<br>]</p>
<h2 id="2、配置jwt验证"><a href="#2、配置jwt验证" class="headerlink" title="2、配置jwt验证"></a>2、配置jwt验证</h2><p>REST_FRAMEWORK = {<br>    # 身份认证<br>    ‘DEFAULT_AUTHENTICATION_CLASSES’: (<br>        ‘rest_framework_jwt.authentication.JSONWebTokenAuthentication’,<br>        ‘rest_framework.authentication.SessionAuthentication’,<br>        ‘rest_framework.authentication.BasicAuthentication’,<br>    ),<br>}</p>
<p>import datetime</p>
<p>JWT_AUTH = {<br>    ‘JWT_AUTH_HEADER_PREFIX’: ‘JWT’,<br>    ‘JWT_EXPIRATION_DELTA’: datetime.timedelta(days=1),<br>    ‘JWT_RESPONSE_PAYLOAD_HANDLER’:<br>        ‘users.views.jwt_response_payload_handler’,  # 重新login登录返回函数<br>}<br>AUTH_USER_MODEL=’users.User’  # 指定使用users APP中的 model User进行验证<br>settings.py 配置使用JWT</p>
<p>from django.contrib import admin<br>from django.urls import path,re_path,include</p>
<p>urlpatterns = [<br>    path(‘admin/‘, admin.site.urls),<br>    re_path(r’users/‘,include((‘users.urls’,’users’),namespace=’users’))<br>]</p>
<p>urls.py</p>
<p>from django.urls import path,re_path,include<br>from users import views<br>from rest_framework_jwt.views import obtain_jwt_token  # 验证密码后返回token</p>
<p>urlpatterns = [<br>    path(‘v1/register/‘, views.RegisterView.as_view(), name=’register’),  # 注册用户<br>    path(‘v1/login/‘, obtain_jwt_token,name=’login’),  # 用户登录后返回token<br>    path(‘v1/list/‘, views.UserList.as_view(), name=’register’),  # 测试需要携带token才能访问<br>]</p>
<p>users/urls.py</p>
<p>from django.db import models<br>from django.contrib.auth.models import AbstractUser</p>
<p>class User(AbstractUser):<br>    username = models.CharField(max_length=64, unique=True)<br>    password = models.CharField(max_length=255)<br>    phone = models.CharField(max_length=64)<br>    token = models.CharField(max_length=255)</p>
<h2 id="serializers-py"><a href="#serializers-py" class="headerlink" title="serializers.py"></a>serializers.py</h2><p>from rest_framework_jwt.settings import api_settings<br>from rest_framework import serializers<br>from users.models import User</p>
<p>class UserSerializer(serializers.Serializer):<br>    username = serializers.CharField()<br>    password = serializers.CharField()<br>    phone = serializers.CharField()<br>    token = serializers.CharField(read_only=True)</p>
<pre><code>def create(self, data):
    user = User.objects.create(**data)
    user.set_password(data.get(&#39;password&#39;))
    user.save()
    # 补充生成记录登录状态的token
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    payload = jwt_payload_handler(user)
    token = jwt_encode_handler(payload)
    user.token = token
    return user</code></pre>
<p>users/serializers.py 使用Serializer的create方法创建token</p>
<p>from django.shortcuts import render<br>import json<br>from rest_framework.views import APIView<br>from rest_framework.views import Response<br>from rest_framework.permissions import IsAuthenticated<br>from rest_framework_jwt.authentication import JSONWebTokenAuthentication<br>from users.serializers import UserSerializer</p>
<h3 id="用户注册"><a href="#用户注册" class="headerlink" title="用户注册"></a>用户注册</h3><p>class RegisterView(APIView):<br>    def post(self, request, *args, **kwargs):<br>        serializer = UserSerializer(data=request.data)<br>        if serializer.is_valid():<br>            serializer.save()<br>            return Response(serializer.data, status=201)<br>        return Response(serializer.errors, status=400)</p>
<h3 id="重新用户登录返回函数"><a href="#重新用户登录返回函数" class="headerlink" title="重新用户登录返回函数"></a>重新用户登录返回函数</h3><p>def jwt_response_payload_handler(token, user=None, request=None):<br>    ‘’’<br>    :param token: jwt生成的token值<br>    :param user: User对象<br>    :param request: 请求<br>    ‘’’<br>    return {<br>        ‘token’: token,<br>        ‘user’: user.username,<br>        ‘userid’: user.id<br>    }</p>
<h3 id="测试必须携带token才能访问接口"><a href="#测试必须携带token才能访问接口" class="headerlink" title="测试必须携带token才能访问接口"></a>测试必须携带token才能访问接口</h3><p>class UserList(APIView):<br>    permission_classes = [IsAuthenticated]  # 接口中加权限<br>    authentication_classes = [JSONWebTokenAuthentication]</p>
<pre><code>def get(self,request, *args, **kwargs):
    print(request.META.get(&#39;HTTP_AUTHORIZATION&#39;, None))
    return Response(&#123;&#39;name&#39;:&#39;zhangsan&#39;&#125;)
def post(self,request, *args, **kwargs):
    return Response(&#123;&#39;name&#39;:&#39;zhangsan&#39;&#125;)</code></pre>
<p>users/views.py</p>
<p>users/models.py 添加用户认证的User表</p>
<p>###1、指定允许的hosts，否则通过 <a target="_blank" rel="noopener" href="http://jack.com:8888/index/">http://jack.com:8888/index/</a> 无法访问jack_django程序<br>ALLOWED_HOSTS = [‘*’]</p>
<p>###2、将corsheaders 注册到app中<br>INSTALLED_APPS = [<br>    ‘django.contrib.admin’,<br>    ‘django.contrib.auth’,<br>    ‘django.contrib.contenttypes’,<br>    ‘django.contrib.sessions’,<br>    ‘django.contrib.messages’,<br>    ‘django.contrib.staticfiles’,<br>    ‘corsheaders’,<br>    ‘app01’,<br>]</p>
<p>###3、将下面两条添加到中间件重<br>MIDDLEWARE = [<br>    ‘corsheaders.middleware.CorsMiddleware’,<br>    ‘django.middleware.common.CommonMiddleware’,<br>]</p>
<p>###4、配置 django-cors-headers 中的参数<br>CORS_ALLOW_CREDENTIALS = True<br>CORS_ORIGIN_ALLOW_ALL = True</p>
<p>CORS_ORIGIN_WHITELIST = (</p>
<p>‘*’,</p>
<h6 id=""><a href="#" class="headerlink" title=")"></a>)</h6><p>CORS_ALLOW_METHODS = (<br>    ‘DELETE’,<br>    ‘GET’,<br>    ‘OPTIONS’,<br>    ‘PATCH’,<br>    ‘POST’,<br>    ‘PUT’,<br>    ‘VIEW’,<br>)</p>
<p>CORS_ALLOW_HEADERS = (<br>    ‘XMLHttpRequest’,<br>    ‘X_FILENAME’,<br>    ‘accept-encoding’,<br>    ‘authorization’,<br>    ‘content-type’,<br>    ‘dnt’,<br>    ‘origin’,<br>    ‘user-agent’,<br>    ‘x-csrftoken’,<br>    ‘x-requested-with’,<br>    ‘Pragma’,<br>)</p>
<p>settings.py 前后端分离配置cors</p>
<h3 id="通过用户token获取用户信息"><a href="#通过用户token获取用户信息" class="headerlink" title="通过用户token获取用户信息"></a>通过用户token获取用户信息</h3><p>from rest_framework_jwt.utils import jwt_decode_handler<br>toke_user = jwt_decode_handler(token)<br> {‘user_id’: 2, ‘username’: ‘lisi’, ‘exp’: 1561504444, ‘email’: ‘’}</p>
<p>1、cookie使用原理</p>
<p>　　　　　　1.用户向服务器发送用户名和密码。</p>
<p>　　　　　　2.验证服务器后，相关数据（如用户角色，登录时间等）将保存在当前会话中。</p>
<p>　　　　　　3.服务器向用户返回session_id，session信息都会写入到用户的Cookie。</p>
<p>　　　　　　4.用户的每个后续请求都将通过在Cookie中取出session_id传给服务器。</p>
<p>　　　　　　5.服务器收到session_id并对比之前保存的数据，确认用户的身份。</p>
<p>　　　　　　</p>
<p>　　2、session使用缺点</p>
<pre><code>  　　　　　　1. 这种模式最大的问题是，没有分布式架构，无法支持横向扩展。
  　　　　　　2. 如果使用一个服务器，该模式完全没有问题。
  　　　　　　3. 但是，如果它是服务器群集或面向服务的跨域体系结构的话，则需要一个统一的session数据库库来保存会话数据实现共享，
  　　　　　　4. 这样负载均衡下的每个服务器才可以正确的验证用户身份。</code></pre>
<p>　　3、常用解决session方法</p>
<pre><code>  　　　　　　1. 一种解决方案是通过持久化session数据，写入数据库或文件持久层等。
  　　　　　　2. 收到请求后，验证服务从持久层请求数据。
  　　　　　　3. 依赖于持久层的数据库或者问题系统，会有单点风险，如果持久层失败，整个认证体系都会挂掉。</code></pre>
<h2 id="1-2-JWT的介绍"><a href="#1-2-JWT的介绍" class="headerlink" title="1.2  JWT的介绍"></a>1.2  JWT的介绍</h2><h3 id="1、jwt-原则"><a href="#1、jwt-原则" class="headerlink" title="1、jwt 原则"></a>1、jwt 原则</h3><p>JWT的原则是在服务器身份验证之后，将生成一个JSON对象并将其发送回用户<br>{<br>“UserName”: “Chongchong”,<br>“Role”: “Admin”,<br>“Expire”: “2018-08-08 20:15:56”<br>}</p>
<p>之后，当用户与服务器通信时，客户在请求中发回JSON对象，服务器仅依赖于这个JSON对象来标识用户。<br>为了防止用户篡改数据，服务器将在生成对象时添加签名（有关详细信息，请参阅下文）。服务器不保存任何会话数据，即服务器变为无状态，使其更容易扩展</p>
<h3 id="2、JWT的数据结构"><a href="#2、JWT的数据结构" class="headerlink" title="2、JWT的数据结构"></a>2、JWT的数据结构</h3><p>　　　　　　1）jwt头：JWT头部分是一个描述JWT元数据的JSON对象</p>
<p>　　　　　　2）有效载荷：七个默认字段+自定义私有字段</p>
<p>　　　　　　3）签名=HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload),secret)</p>
<p>　　　　　　</p>
<h3 id="JWT头"><a href="#JWT头" class="headerlink" title="JWT头"></a>JWT头</h3><p> JWT头部分是一个描述JWT元数据的JSON对象，通常如下所示。<br>{<br>“alg”: “HS256”,<br>“typ”: “JWT”<br>}<br> 1）alg属性表示签名使用的算法，默认为HMAC SHA256（写为HS256）；<br> 2）typ属性表示令牌的类型，JWT令牌统一写为JWT。<br>3）最后，使用Base64 URL算法将上述JSON对象转换为字符串保存。</p>
<h3 id="2）有效载荷"><a href="#2）有效载荷" class="headerlink" title="2）有效载荷"></a>2）有效载荷</h3><p>###1、有效载荷部分，是JWT的主体内容部分，也是一个JSON对象，包含需要传递的数据。 JWT指定七个默认字段供选择。<br>‘’’<br>iss：发行人<br>exp：到期时间<br>sub：主题<br>aud：用户<br>nbf：在此之前不可用<br>iat：发布时间<br>jti：JWT ID用于标识该JWT<br>‘’’</p>
<p>###2、除以上默认字段外，我们还可以自定义私有字段，如下例：<br>{<br>“sub”: “1234567890”,<br>“name”: “chongchong”,<br>“admin”: true<br>}</p>
<h3 id="3、注意"><a href="#3、注意" class="headerlink" title="3、注意"></a>3、注意</h3><p>默认情况下JWT是未加密的，任何人都可以解读其内容，因此不要构建隐私信息字段，存放保密信息，以防止信息泄露。<br>JSON对象也使用Base64 URL算法转换为字符串保存。</p>
<h3 id="有效载荷"><a href="#有效载荷" class="headerlink" title="有效载荷"></a>有效载荷</h3><h3 id="3）签名哈希"><a href="#3）签名哈希" class="headerlink" title="3）签名哈希"></a>3）签名哈希</h3><p>1.签名哈希部分是对上面两部分数据签名，通过指定的算法生成哈希，以确保数据不会被篡改。<br> 2.首先，需要指定一个密码（secret），该密码仅仅为保存在服务器中，并且不能向用户公开。<br> 3.然后，使用标头中指定的签名算法（默认情况下为HMAC SHA256）根据以下公式生成签名。<br> 4.HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload),secret)<br> 5.在计算出签名哈希后，JWT头，有效载荷和签名哈希的三个部分组合成一个字符串，每个部分用”.”分隔，就构成整个JWT对象。</p>
<h3 id="3、jwt核心"><a href="#3、jwt核心" class="headerlink" title="3、jwt核心"></a>3、jwt核心</h3><p>　　　　　　1）给用户颁发的token值相当于一把锁，服务器端的秘钥相当于一把钥匙</p>
<p>　　　　　　2）每次客户端请求都会携带这把锁，服务器端用秘钥去开这把锁，若果无法打开就证明是伪造的</p>
<h3 id="4、jwt特点分析"><a href="#4、jwt特点分析" class="headerlink" title="4、jwt特点分析"></a>4、jwt特点分析</h3><p>　　　　　　1、JWT默认不加密，但可以加密，生成原始令牌后，可以使用改令牌再次对其进行加密。</p>
<p>　　　　　　2、当JWT未加密方法是，一些私密数据无法通过JWT传输。</p>
<p>　　　　　　3、JWT不仅可用于认证，还可用于信息交换，善用JWT有助于减少服务器请求数据库的次数。</p>
<p>　　　　　　4、JWT的最大缺点是服务器不保存会话状态，所以在使用期间不可能取消令牌或更改令牌的权限，一旦JWT签发，在有效期内将会一直有效。</p>
<p>　　　　　　5、JWT本身包含认证信息，因此一旦信息泄露，任何人都可以获得令牌的所有权限。</p>
<p>　　　　　　6、为了减少盗用和窃取，JWT不建议使用HTTP协议来传输代码，而是使用加密的HTTPS协议进行传输。</p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/01/19/jwt%E7%9A%84%E4%BD%BF%E7%94%A8/">
    <time datetime="2021-01-19T11:43:18.000Z" class="entry-date">
        2021-01-19
    </time>
</a>
    
    
    </footer>
</article>






  
    <article id="post-工厂模式" class="post-工厂模式 post type-post status-publish format-standard hentry">
    <!---->

      <header class="entry-header">
        
        
  
    <h1 class="entry-title">
      <a class="article-title" href="/tefuir/2021/01/16/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/">工厂模式</a>
    </h1>
  

        
        <div class="comments-link">
            
            <a href="javascript:void(0);" data-url="https://yanlidoushikeke.gitee.io/myhexo/2021/01/16/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/" data-id="ckkttwp6t0004csu063gpbu1j" class="leave-reply bdsharebuttonbox" data-cmd="more">Share</a>
        </div><!-- .comments-link -->
      </header><!-- .entry-header -->

    <div class="entry-content">
      
        <h2 id="工厂模式"><a href="#工厂模式" class="headerlink" title="工厂模式"></a>工厂模式</h2><ul>
<li>工厂方法模式一种创建对象的模式，它被广泛应用在jdk中以及Spring和Struts框架中；</li>
<li>工厂方法模式基于”输入”，应用在超类和多个子类之间的情况，这种模式将创建对象的责任转移到工厂类；</li>
<li>首先让我们学习一下如何在Java中应用工厂方法模式并且学习到工厂方法的优点，另外工厂方法模式也广泛应用在jdk中；</li>
<li>超类可以是接口、抽象类、父类，本例中将通过重写 toString() 方法来解释工厂方法模式；</li>
</ul>
<h2 id="应用实例："><a href="#应用实例：" class="headerlink" title="应用实例："></a>应用实例：</h2><p> 1、您需要一辆汽车，可以直接从工厂里面提货，而不用去管这辆汽车是怎么做出来的，以及这个汽车里面的具体实现。<br>  2、Hibernate 换数据库只需换方言和驱动就可以。</p>
<h2 id="优点："><a href="#优点：" class="headerlink" title="优点："></a>优点：</h2><p> 1、一个调用者想创建一个对象，只要知道其名称就可以了。<br>  2、扩展性高，如果想增加一个产品，只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现，调用者只关心产品的接口。</p>
<h2 id="缺点："><a href="#缺点：" class="headerlink" title="缺点："></a>缺点：</h2><p>每次增加一个产品时，都需要增加一个具体类和对象实现工厂，使得系统中类的个数成倍增加，在一定程度上增加了系统的复杂度，同时也增加了系统具体类的依赖。这并不是什么好事。</p>
<h2 id="使用场景："><a href="#使用场景：" class="headerlink" title="使用场景："></a>使用场景：</h2><p>1、日志记录器：记录可能记录到本地硬盘、系统事件、远程服务器等，用户可以选择记录日志到什么地方。<br> 2、数据库访问，当用户不知道最后系统采用哪一类数据库，以及数据库可能有变化时。<br>  3、设计一个连接服务器的框架，需要三个协议，”POP3”、”IMAP”、”HTTP”，可以把这三个作为产品类，共同实现一个接口<br>  4.三方登录（比如：微博，钉钉）</p>

      
    </div><!-- .entry-content -->

    <footer class="entry-meta">
    <a href="/tefuir/2021/01/16/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/">
    <time datetime="2021-01-16T09:16:17.000Z" class="entry-date">
        2021-01-16
    </time>
</a>
    
    
    </footer>
</article>






  
  
    <nav id="pagination">
      <nav id="page-nav">
        <a class="extend prev" rel="prev" href="/tefuir/page/2/">&amp;laquo; Prev</a><a class="page-number" href="/tefuir/">1</a><a class="page-number" href="/tefuir/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/tefuir/page/4/">4</a><a class="extend next" rel="next" href="/tefuir/page/4/">Next &amp;raquo;</a>
      </nav>
    </nav>
  

</div></div>
        <div id="secondary" class="widget-area" role="complementary">
  
    <aside id="search" class="widget widget_search"><form role="search" method="get" accept-charset="utf-8" id="searchform" class="searchform" action="//google.com/search">
    <div>
        <input type="text" value="" name="s" id="s" />
        <input type="submit" id="searchsubmit" value="搜索" />
    </div>
</form></aside>
  
    
  
    
  
    
  <aside class="widget">
    <h3 class="widget-title">Recents</h3>
    <div class="widget-content">
      <ul>
        
          <li>
            <a href="/tefuir/2021/04/26/python%E5%9F%BA%E7%A1%80%E7%90%86%E8%AE%BA%E5%AE%9D%E5%85%B8/">python基础理论宝典</a>
          </li>
        
          <li>
            <a href="/tefuir/2021/04/23/python3-Flask%E7%BB%93%E5%90%88Socket-io%E7%AE%80%E5%8D%95%E5%AE%9E%E7%8E%B0%E5%9C%A8%E7%BA%BF%E5%AE%A2%E6%9C%8D%E7%B3%BB%E7%BB%9F/">python3+Flask结合Socket.io简单实现在线客服系统</a>
          </li>
        
          <li>
            <a href="/tefuir/2021/04/23/win10%E7%B3%BB%E7%BB%9F%E4%B8%8B%E5%88%A9%E7%94%A8docker%E9%83%A8%E7%BD%B2gunicorn-Flask%E6%89%93%E9%80%A0%E7%8B%AC%E7%AB%8B%E9%95%9C%E5%83%8F/">win10系统下利用docker部署gunicorn+Flask打造独立镜像</a>
          </li>
        
          <li>
            <a href="/tefuir/2021/04/23/win10%E7%B3%BB%E7%BB%9F%E4%B8%8B%E5%9F%BA%E4%BA%8Edocker%E9%85%8D%E7%BD%AEelasticsearch%E9%85%8D%E5%90%88python3%E8%BF%9B%E8%A1%8C%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2/">win10系统下基于docker配置elasticsearch配合python3进行全文检索</a>
          </li>
        
          <li>
            <a href="/tefuir/2021/04/23/%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%97%AE%E9%A2%98/">服务器问题</a>
          </li>
        
      </ul>
    </div>
  </aside>

  
    
  
    
  
</div>
      </div>
      <footer id="colophon" role="contentinfo">
    <p>&copy; 2021 南辞
    All rights reserved.</p>
    <p>Powered by <a href="http://hexo.io/" target="_blank">Hexo</a></p>
</footer>
    <script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"1","bdMiniList":false,"bdPic":"","bdStyle":"2","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='/js/share.js'];</script>

<script src="/js/jquery-3.3.1.min.js"></script>


  
<link rel="stylesheet" href="/tefuir/fancybox/jquery.fancybox.css">

  
<script src="/tefuir/fancybox/jquery.fancybox.pack.js"></script>




<script src="/tefuir/js/script.js"></script>


<script src="/js/navigation.js"></script>

<div id="bg"></div>

  </div>
</body>
</html>